package com.itHuangTao.tank.components;

import com.almasb.fxgl.core.util.LazyValue;
import com.almasb.fxgl.dsl.FXGL;
import com.almasb.fxgl.dsl.components.EffectComponent;
import com.almasb.fxgl.entity.Entity;
import com.almasb.fxgl.entity.EntityGroup;
import com.almasb.fxgl.entity.SpawnData;
import com.almasb.fxgl.entity.component.Component;
import com.almasb.fxgl.time.LocalTimer;
import com.itHuangTao.tank.Config;
import com.itHuangTao.tank.GameType;
import com.itHuangTao.tank.effects.EnemyAppearanceEffect;
import com.itHuangTao.tank.effects.FreezeEffect;
import com.itHuangTao.tank.effects.ShipEffect;

import java.util.List;

public class TankComponent extends Component {
    //接受效果组件的变量
    private EffectComponent effectComponent;
    //控制键盘只能接受一次信息
    private boolean movedThisFrame = false;
    //坦克在一段时间内的移动距离(使得坦克每一次的移动像素不一样，根据图片刷新速度决定（防止卡顿卡帧）)
    private double distance;
    //记录每一次移动的方向键
    private Dir moveDir = Dir.UP;
    //时间计时器
    private LocalTimer shootTimer;

    public Dir getMoveDir() {
        return moveDir;
    }

    public void setMoveDir(Dir moveDir)  {
        this.moveDir = moveDir;
    }

    //代表组件，被添加到实体时会调用
    @Override
    public void onAdded() {
        shootTimer = FXGL.newLocalTimer();
    }

    //与障碍物出现碰撞检测变量的创建(说明坦克会遇到的障碍物)
    private final LazyValue<EntityGroup> blockAllLazyValue
            = new LazyValue<>(() -> FXGL.getGameWorld().getGroup(GameType.BORDER,
            GameType.BRICK, GameType.SEA, GameType.STONE, GameType.PLAYER, GameType.ENEMY));

    //少了海洋的碰撞检测
    private final LazyValue<EntityGroup> blockLazyValue
            = new LazyValue<>(() -> FXGL.getGameWorld().getGroup(GameType.BORDER,
            GameType.BRICK, GameType.STONE, GameType.PLAYER, GameType.ENEMY));

    //游戏运行时，这个方法每一帧都会调用，tpf:代表这一帧的用时(一般是60帧每一秒)
    // 移动的距离  时间 * 速度 = 距离
    @Override
    public void onUpdate(double tpf) {
        //如果坦克被冻结就不能执行移动效果
        if (effectComponent.hasEffect(FreezeEffect.class)) {
            return;
        }
        movedThisFrame = false;
        distance = tpf * Config.TANK_MOVE_SPEED;
    }

    //实现上下左右移动和射击
    public void moveUp() {
        if (movedThisFrame) {
            return;
        }
        movedThisFrame = true;//正在这个方向上移动
        entity.setRotation(0);//图片的旋转
        moveDir = Dir.UP;
        move();
    }

    public void moveDown() {
        if (movedThisFrame) {
            return;
        }
        movedThisFrame = true;//正在这个方向上移动
        entity.setRotation(180);//图片的旋转
        moveDir = Dir.DOWN;
        move();
    }

    public void moveLeft() {
        if (movedThisFrame) {
            return;
        }
        movedThisFrame = true;//正在这个方向上移动
        entity.setRotation(270);//图片的旋转
        moveDir = Dir.LEFT;
        move();
    }

    public void moveRight() {
        if (movedThisFrame) {
            return;
        }
        movedThisFrame = true;//正在这个方向上移动
        entity.setRotation(90);//图片的旋转
        moveDir = Dir.RIGHT;
        move();
    }

    public void shoot() {
        if (shootTimer.elapsed(Config.SHOOT_DELAY)) {
            FXGL.spawn("bullet"
                    , new SpawnData(entity.getCenter().subtract(8 / 2.0, 10 / 2.0))//子弹的发射位置)
                            .put("dir", moveDir.getVector())
                            .put("ownerType", entity.getType())//给子弹添加一个阵营识别（同类就不会进行攻击）
                            .put("level", entity.getComponent(TankLevelComponent.class).getValue())//获得坦克的等级
            );
            //时间计数器归0
            shootTimer.capture();
        }
    }

    //控制坦克移动
    public void move() {
        //理论上可以走的最大距离
        int len = (int) distance;
        //判断是否有轮船效果（用于切换障碍物集合类型)
        boolean b = effectComponent.hasEffect(ShipEffect.class);
        //障碍物的集合
        List<Entity> blockList;
        if (b) {
            //无水面障碍物
            blockList = blockLazyValue.get().getEntitiesCopy();
        } else {
            //有水面障碍物
            blockList = blockAllLazyValue.get().getEntitiesCopy();
        }

        //删除自己（避免在碰撞检测时：自己和自己进行碰撞检测）
        blockList.remove(entity);

        int size = blockList.size();
        //判断边界碰撞
        boolean isCollision = false;
        for (int i = 0; i < len; i++) {
            //每次移动都是一个像素一个像素地在移动
            entity.translate(moveDir.getVector().getX(), moveDir.getVector().getY());
            for (int j = 0; j < size; j++) {
                if (entity.isColliding(blockList.get(j))) {
                    isCollision = true;
                    break;
                }
            }
            //如果和边界发生了碰撞（就停止运动）
            if (isCollision) {
                entity.translate(-moveDir.getVector().getX(), -moveDir.getVector().getY());
                break;
            }
        }
    }
}
